use std::{error::Error, path::{Path, PathBuf}};

use log::info;

use crate::{
    AppError, cliargs::TranslateRule, 
    wrappers::ffmpeg_wrapper, 
    helper, 
    subtitles::SubTitles, 
    wrappers::transalte_wrapper, 
    wrappers::whisper_wrapper
};

pub fn audio_convert(
    video_path: &Path,
    audio_file_name: &Option<String>,
) -> Result<PathBuf, Box<dyn Error>> {
    let st = std::time::Instant::now();
    if !video_path.exists() {
        return Err(format!(
            "Video file :{} does not exist",
            video_path.to_str().unwrap()
        )
        .into());
    }

    let audio_file_path = match audio_file_name {
        None => {
            let mut audioname = helper::get_filename_exclude_extension(video_path);
            audioname.push_str("wav");
            video_path.with_file_name(audioname)
        }
        Some(audio_file_name) => video_path.with_file_name(audio_file_name),
    };

    ffmpeg_wrapper::extract_audio_impl(
        video_path.to_str().unwrap(),
        audio_file_path.to_str().unwrap(),
    )?;
    let et = std::time::Instant::now();
    info!("audio_convert took {}ms", (et - st).as_millis());
    Ok(audio_file_path)
}

pub fn srt_extract(
    audio_file: &Path,
    write_io: bool,
    srt_file: &Option<String>,
) -> Result<SrtExtractResult, Box<dyn Error>> {
    let st = std::time::Instant::now();

    if !audio_file.exists() {
        return Err(format!(
            "Audio file :{} does not exist",
            audio_file.to_str().unwrap()
        )
        .into());
    }
    let subtitles = whisper_wrapper::extract_srt(audio_file.to_str().unwrap())?;

    let result = if write_io {
        let srt_file_str = match srt_file {
            Some(srt_file) => srt_file.to_string(),
            None => {
                let mut srt_file = helper::get_filename_exclude_extension(audio_file);
                srt_file.push_str("srt");
                audio_file
                    .with_file_name(srt_file)
                    .to_str()
                    .unwrap()
                    .to_string()
            }
        };
        subtitles.write_to_file(&srt_file_str);
        SrtExtractResult::WirteIo(srt_file_str)
    } else {
        SrtExtractResult::Subtitle(subtitles)
    };
    let et = std::time::Instant::now();
    info!("audio_convert took {}ms", (et - st).as_millis());
    Ok(result)
}

pub enum SrtExtractResult {
    WirteIo(String),
    Subtitle(SubTitles),
}

pub async  fn srt_translate(
    srt_file: &Path,
    trans_rule: &Option<TranslateRule>,
) -> Result<(), AppError> {
    let st = std::time::Instant::now();
    if !srt_file.exists() {
        return Err(format!("Srt file :{} does not exist", srt_file.to_str().unwrap()).into());
    }
    let mut subtitles = SubTitles::load_from_file(srt_file);
    srt_translate_impl(&mut subtitles, trans_rule).await?;
    let et=std::time::Instant::now();
    info!("srt_translate took {}ms", (et - st).as_millis());
    Ok(())
}
pub async fn srt_translate_impl(
    subtitles: &mut SubTitles,
    trans_rule: &Option<TranslateRule>)->Result<(),AppError>{
    transalte_wrapper::translate(subtitles,trans_rule).await?;
    Ok(())
    }